package org.smile.strate;

import java.io.IOException;
import java.lang.reflect.Method;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.smile.strate.handler.BeanHandler;
import org.smile.strate.handler.SpringBeanHandler;
import org.smile.strate.handler.StrateBeanHandler;
/**
 * actionservlet 所有的action请求都是通过此servlet处理 
 * 
 * 根据不同的路径实例化不能的action类 调用 方法 
 * 
 * @author strive
 *
 */
public class ActionServlet extends HttpServlet {
	/**
	 * action实例化的处理类
	 */
	private BeanHandler handler;
	/**
	 * 字符编码
	 */
	private String encode="UTF-8";
	/**
	 * url结尾
	 */
	private String urlEnd=".action";
	
	public void destroy() {
		super.destroy(); // Just puts "destroy" string in log
	}
	/**
	 * get处理
	 */
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doService(request, response, Action.GET_TYPE);
	}
	/**
	 * POST处理
	 */
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doService(request, response, Action.POST_TYPE);
	}
	/**
	 * 服务处理，从配置文件读取信息 
	 * 实例化 类 反射方法 如果配置文件中没有指定method 
	 *  也可以从客户端传来一个参数 method 
	 * 由method决定调用哪个方法
	 * @param request
	 * @param response
	 * @param do_type
	 * @throws ServletException
	 * @throws IOException
	 */
	protected void doService(HttpServletRequest request,HttpServletResponse response,int do_type) throws ServletException, IOException
	{
		request.setCharacterEncoding(encode);
		response.setCharacterEncoding(encode);
		String url = request.getRequestURI();
		if (url.endsWith(urlEnd)){
			String contextPath=request.getContextPath();
			//servlet路径
			String servletUrl = url.substring(url.lastIndexOf(contextPath)+contextPath.length(),url.lastIndexOf("."));
			//
			ActionElement actionElement=ActionContext.getActionElement(servletUrl);
			if(actionElement==null){
				throw new ServletException("no action find that named "+servletUrl);
			}
			//先从配置文件获取方法 如果没有配置 再从提交参数中获取 还是没有 则抛出异常
			String methodName=actionElement.getMethod();
			if(methodName==null){
				methodName=request.getParameter("method");
			}
			if(methodName==null||"".equals(methodName)){
				throw new ServletException("please give a designated parameter method ");
			}
			try {
				//得到action实例
				Object service=this.handler.getActionBean(actionElement.getClazz(), request.getSession().getServletContext());
				Method initPerterties=service.getClass().getMethod("initPerterties",new Class[]{HttpServletRequest.class,HttpServletResponse.class,Integer.class,String.class});
				//初始化方法
				Method method=service.getClass().getMethod(methodName,new Class[]{});
				initPerterties.invoke(service, request,response,do_type,encode);
				//处理服务方法
				String result=(String) method.invoke(service, null);
				if(result!=null){
					ActionForward forward=actionElement.getForwards().get(result);
					if(forward==null){
						throw new ServletException("the forward name "+result+" not find in the strate config xml file");
					}else if(forward.getType()==null||ActionForward.FORWARD.equals(forward.getType())){
						//服务器端跳转
						request.getRequestDispatcher(forward.getResult()).forward(request, response);
					}else if(ActionForward.REDIRECT.equals(forward.getType())){
						//重定向
						String resultUrl=forward.getResult();
						if(resultUrl.contains("http:")){
							response.sendRedirect(forward.getResult());
						}else{
							response.sendRedirect(request.getContextPath()+resultUrl);
						}
					}else {
						throw new ServletException("unknown forward type ,please check the strate xml config file"); 
					}
				}
			} catch (SecurityException e) {
				throw new ServletException("invoke method：["+this.getClass().getName()+"."+methodName+"] have a error ",e);
			} catch (NoSuchMethodException e) {
				throw new ServletException("invoke method：["+this.getClass().getName()+"."+methodName+"] have a error ,no such method",e);
			}catch(Exception e){
				throw new ServletException("service ==>"+getClass().getName()+"do method "+methodName+" has a error ",e);
			}
		}
	}
	@Override
	public void init() throws ServletException {
		super.init();
		String urlEnd=this.getInitParameter("urlEnd");
		String encode=this.getInitParameter("encode");
		String isSpring=this.getInitParameter("springSupport");
		if(urlEnd!=null){
			this.urlEnd="."+urlEnd;
		}
		if(encode!=null){
			this.encode=encode;
		}
		if("true".equals(isSpring)){
			this.handler=new SpringBeanHandler();
		}else{
			this.handler=new StrateBeanHandler();
		}
	}
}
